package com.shopmall.controller.system;


import com.alibaba.fastjson.JSON;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.shopmall.common.ResponseData;
import com.shopmall.system.service.impl.UserService;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
public class LoginController extends ResponseData {
    @Resource
    UserService userService;
    @Resource
    BCryptPasswordEncoder passwordEncoder;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;

    @PostMapping("/login")
    public ResponseData doLogin(@RequestBody Map<String,String> paramMap) {

        String username = paramMap.get("username");
        Object number = redisTemplate.opsForValue().get(username);
        if(number!=null && 2==Integer.valueOf(number+"")){
            Map<String,String> map = new HashMap<>();
            String messageId = UUID.randomUUID().toString();
            map.put("messageId",messageId);
            map.put("userName","123456");
            map.put("password","111111");
            map.put("createTime",System.currentTimeMillis()+"");
            String messageData = JSON.toJSONString(map);
            rabbitTemplate.convertAndSend("76-exchanges","routingKey",messageData);
//            redisTemplate.expire(username,100,TimeUnit.SECONDS);
            return this.failed("账号被锁定");
        }
        if(number!=null && 2<Integer.valueOf(number+"")){
            return this.failed("密码错误，您还能尝试"+(5-Integer.valueOf(number+""))+"次");
        }
        String password = paramMap.get("password");
        String code = paramMap.get("code");

        String kaptchaCode = String.valueOf(redisTemplate.opsForValue().get("kaptchaCode"));
        if (!kaptchaCode.equalsIgnoreCase(code)) {
            return this.failed("验证码不正确");
        }
        try {
            UserDetails userDetails = userService.loadUserByUsername(username);
            if (!passwordEncoder.matches(password, userDetails.getPassword())) {
                //错误密码次数保存
                redisTemplate.opsForValue().increment(username,1L);
                redisTemplate.expire(username,100,TimeUnit.SECONDS);
                return this.failed("用户名或密码不正确");
            }
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);

            Map<String, Object> map = new HashMap<>();
            map.put("sub", userDetails.getUsername());
            map.put("created", new Date().toLocaleString());
            // ...
            long now = System.currentTimeMillis();//当前时间
            long exp = now + 1000*60*5;//过期时间为5分钟
            String jwtToken = Jwts.builder().setExpiration(new Date(exp))
                    .setClaims(map)
                    .signWith(SignatureAlgorithm.HS512, "abcerwrw")
                    .compact();
            return success(jwtToken);
        } catch (UsernameNotFoundException e) {
            return this.failed("用户名或密码不正确");
        }

    }

    @GetMapping("/code")
    public void kaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 定义响应输出类型为图片格式
        response.setContentType("image/jpeg");
        // 不缓存响应内容
        response.setHeader("Cache-Control", "no-store, no-cache");
        DefaultKaptcha captchaProducer = new DefaultKaptcha();
        captchaProducer.setConfig(new Config(new Properties()));
        // 获取验证码字符串并将其绑定到 session 中
        String kaptchaText = captchaProducer.createText();
        redisTemplate.opsForValue().set("kaptchaCode",kaptchaText.trim(),60, TimeUnit.SECONDS);
        // 生成验证码图片并输出到响应输出流中
        BufferedImage kaptchaImage = captchaProducer.createImage(kaptchaText);
        ServletOutputStream servletOutputStream = response.getOutputStream();
        ImageIO.write(kaptchaImage, "jpg", servletOutputStream);
        servletOutputStream.flush();
        servletOutputStream.close();
    }
}
